using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;

namespace Microsoft.Cryptography
{
    /// <summary>
    /// Base signature description class for for all supported hashalgorithms, which will call the RSAManaged class.
    /// <seealso cref="Microsoft.Cryptography.RSAPKCS1SHA512SignatureDescription"/>
    /// <seealso cref="Microsoft.Cryptography.RSAPKCS1SHA384SignatureDescription"/>
    /// <seealso cref="Microsoft.Cryptography.RSAPKCS1SHA256SignatureDescription"/>
    /// <seealso cref="Microsoft.Cryptography.RSAPKCS1SHA1SignatureDescription"/>
    /// <seealso cref="Microsoft.Cryptography.RSAPKCS1RIPEMD160SignatureDescription"/>
    /// <seealso cref="Microsoft.Cryptography.RSAPKCS1MD5SignatureDescription"/>
    /// </summary>
    public abstract class RSAManagedPKCS1SignatureDescription : SignatureDescription
    {
        private static string _keyAlgorithm = string.Empty;

        private static string keyAlgorithm
        {
            get
            {
                if (string.IsNullOrEmpty(_keyAlgorithm))
                {
                    lock (_keyAlgorithm)
                    {
                        if (string.IsNullOrEmpty(_keyAlgorithm))
                        {
                            object dummy = CryptoConfig.CreateFromName("RSABase");

                            if ((dummy == null) || !(dummy is RSABase))
                            {
                                throw new Exception("The RSA-class configured in machine.config for setting 'RSABase' must derive from Microsoft.Cryptography.RSABase!");
                            }

                            _keyAlgorithm = dummy.GetType().AssemblyQualifiedName;
                        }
                    }
                }

                return _keyAlgorithm;
            }
        }

        /// <summary>
        /// The current hash algorithm.
        /// Possible values are:
        ///     MD5, 
        ///     SHA1, 
        ///     SHA256, 
        ///     SHA384, 
        ///     SHA512, 
        ///     RIPEMD160
        /// </summary>
        protected string _hashAlgorithm;

        /// <summary>
        /// Creates instance of RSAManagedPKCS1SignatureDescription class
        /// </summary>
        /// <param name="digestAlgorithm">String value which represents digest algorithm class. 
        /// Possible values are 
        ///     System.Security.Cryptography.MD5
        ///     System.Security.Cryptography.RIPEMD160Managed
        ///     System.Security.Cryptography.SHA1CryptoServiceProvider
        ///     System.Security.Cryptography.SHA256CryptoServiceProvider
        ///     System.Security.Cryptography.SHA384CryptoServiceProvider
        ///     System.Security.Cryptography.SHA512CryptoServiceProvider
        /// </param>
        public RSAManagedPKCS1SignatureDescription(string digestAlgorithm)
        {
            base.KeyAlgorithm = keyAlgorithm;
            base.DigestAlgorithm = digestAlgorithm;
            base.FormatterAlgorithm = "Microsoft.Cryptography.RSAManagedSignatureFormatter";
            base.DeformatterAlgorithm = "Microsoft.Cryptography.RSAManagedSignatureDeformatter";
        }

        /// <summary>
        /// Creates a RSAManaged-SignatureDeformatter.
        /// </summary>
        /// <param name="key">The amsymetric algorithm</param>
        /// <returns>
        /// Returns a Microsoft.Cryptography.RSAManagedSignatureDeformatter instance.
        /// <seealso cref="Microsoft.Cryptography.RSAManagedSignatureDeformatter"/>
        /// </returns>
        public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
        {
            AsymmetricSignatureDeformatter deformatter =
                (AsymmetricSignatureDeformatter)CryptoConfig.CreateFromName(base.DeformatterAlgorithm);
            deformatter.SetKey(key);
            //deformatter.SetHashAlgorithm("SHA256");
            deformatter.SetHashAlgorithm(_hashAlgorithm);
            return deformatter;
        }

        /// <summary>
        /// Creates a RSAManaged-SignatureFormatter.
        /// </summary>
        /// <param name="key">The amsymetric algorithm</param>
        /// <returns>
        /// Returns a Microsoft.Cryptography.RSAManagedSignatureFormatter instance.
        /// <seealso cref="Microsoft.Cryptography.RSAManagedSignatureFormatter"/>
        /// </returns>
        public override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key)
        {
            AsymmetricSignatureFormatter formatter = (AsymmetricSignatureFormatter)CryptoConfig.CreateFromName(base.FormatterAlgorithm);
            formatter.SetKey(key);
            return formatter;
        }
    }
}
